using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System.Data;

namespace GenericExampleParticleSystem
{
    class DrawMesh : DrawableGameComponent
    {
        //device stuff
        ContentManager content;
        GraphicsDeviceManager myDeviceManager;
        GraphicsDevice myDevice;

        //world view info
        public Vector3 myPosition;
        public Vector3 myScale;
        public Quaternion myRotation;
        
        //texture stuff
        string textureAsset;
        Texture2D myTexture;
        //shader stuff
        string shaderAsset;
        Effect effect;

        // vertex declaration for a triangle
        private VertexDeclaration posColTriangle;

        //Triangle Array
        VertexPositionColor[] vertices;
        private int WIDTH = 4;
        private int DEPTH = 3;
        private VertexBuffer vb;
        private IndexBuffer ib;

        //Note, No Initialize Method, that is all handeled by the Game1.cs
        public DrawMesh(Game game, GraphicsDeviceManager graphiceDeviceManager, string texture, string shader):base(game)
        {
            content = new ContentManager(game.Services);
            myDeviceManager = graphiceDeviceManager;
            
            //the texture file
            textureAsset = texture;
            //the shader/effect file
            shaderAsset = shader;

            //world view
            myPosition = Vector3.Zero;
            myScale = Vector3.One;
            myRotation = new Quaternion(0, 0, 0, 1);

        }
        private void SetUpVertices()
        {
            vertices = new VertexPositionColor[WIDTH * DEPTH];
            for (int x = 0; x < WIDTH; x++)
            {
                for (int y = 0; y < DEPTH; y++)
                {
                    vertices[x + y * WIDTH].Position = new Vector3(x, 10, y);
                    vertices[x + y * WIDTH].Color = Color.White;
                }
            }

            vb = new VertexBuffer(myDevice, sizeof(float) * 4 * WIDTH * DEPTH, BufferUsage.WriteOnly);
            vb.SetData(vertices);
        }
        private void SetUpIndices()
        {
            int[] indices = new int[(WIDTH - 1) * (DEPTH - 1) * 3];
            for (int x = 0; x < WIDTH - 1; x++)
            {
                for (int y = 0; y < DEPTH - 1; y++)
                {
                    indices[(x + y * (WIDTH - 1)) * 3] = (x + 1) + (y + 1) * WIDTH;
                    indices[(x + y * (WIDTH - 1)) * 3 + 1] = (x + 1) + y * WIDTH;
                    indices[(x + y * (WIDTH - 1)) * 3 + 2] = x + y * WIDTH;
                }
            }

            ib = new IndexBuffer(myDevice, typeof(int), (WIDTH - 1) * (DEPTH - 1) * 3, BufferUsage.WriteOnly);
            ib.SetData(indices);
        }
        #region seting up of vars for var, wvp rotation, translation and revolving
        //what actually calls these methods ?
        /*
        public void Rotate(Vector3 axis, float angle)
        {
            axis = Vector3.Transform(axis, Matrix.CreateFromQuaternion(myRotation));
            myRotation = Quaternion.Normalize(Quaternion.CreateFromAxisAngle(axis, angle) * myRotation);

        }
        public void Translate(Vector3 distance)
        {
            myPosition += Vector3.Transform(distance, Matrix.CreateFromQuaternion(myRotation));
        }

        public void Revolve(Vector3 target, Vector3 axis, float angle)
        {
            Rotate(axis, angle);
            Vector3 revolveAxis = Vector3.Transform(axis, Matrix.CreateFromQuaternion(myRotation));
            Quaternion rotate = Quaternion.CreateFromAxisAngle(revolveAxis, angle);
            myPosition = Vector3.Transform(target - myPosition, Matrix.CreateFromQuaternion(rotate));
        }*/
        #endregion
        protected override void UnloadContent()
        {
            content.Unload();
            base.UnloadContent();
        }
        protected override void LoadContent()
        {
            //get the device from contructor
            myDevice = myDeviceManager.GraphicsDevice;
            //load the texture
            myTexture = content.Load<Texture2D>(textureAsset);

            //load the shader
            effect = content.Load<Effect>(shaderAsset);

            //vertex declaration
            posColTriangle = new VertexDeclaration(myDevice, VertexPositionColor.VertexElements);
            //create triangles
            SetUpVertices();
            SetUpIndices();
            
            base.LoadContent();
        }

        private void createMesh()
        {

        }
        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
        }
        public override void Draw(GameTime gameTime)
        {
            myDevice.RenderState.CullMode = CullMode.None;
            

            Matrix wvp = (Matrix.CreateScale(myScale) * Matrix.CreateFromQuaternion(myRotation) * Matrix.CreateTranslation(myPosition)) * Camera.myView * Camera.myProjection;
            effect.Parameters["WorldViewProj"].SetValue(wvp);

            myDevice.VertexDeclaration = posColTriangle;
            
            //myDevice.RenderState.FillMode = FillMode.WireFrame;
            effect.Begin();
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                
                pass.Begin();
                myDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, WIDTH * DEPTH, 0, (WIDTH - 1) * (DEPTH - 1));
                pass.End();

            }
            effect.End();
            //myDevice.RenderState.FillMode = FillMode.Solid;

            base.Draw(gameTime);
        } 
    }
}
